package tms.ui;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.Calendar;
import java.util.Map;
import java.util.TreeMap;

import org.eclipse.nebula.widgets.ganttchart.GanttChart;
import org.eclipse.nebula.widgets.ganttchart.GanttEvent;
import org.eclipse.nebula.widgets.ganttchart.IColorManager;
import org.eclipse.nebula.widgets.ganttchart.ILanguageManager;
import org.eclipse.nebula.widgets.ganttchart.IPaintManager;
import org.eclipse.nebula.widgets.ganttchart.ISettings;
import org.eclipse.swt.widgets.Composite;

import tms.model.Project;
import tms.model.Task;

/**
 * The class TMSGanttChart a Gantt chart
 * It extends AbstractModelObject and implements PropertyChangeListener
 * to allow the fire of property changes
 * 
 * @author Rolf Schmidt
 * @version 1.0
 */
public class TMSGanttChart extends GanttChart implements PropertyChangeListener {

	public TMSGanttChart(Composite parent, int style, ISettings settings, IColorManager colorManager, IPaintManager paintManager, ILanguageManager languageManager) {
		super(parent, style, settings, colorManager, paintManager, languageManager);
	}

	private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

	public void addPropertyChangeListener(PropertyChangeListener listener) {
		propertyChangeSupport.addPropertyChangeListener(listener);
	}

	public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
		propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
	}

	public void removePropertyChangeListener(PropertyChangeListener listener) {
		propertyChangeSupport.removePropertyChangeListener(listener);
	}

	public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
		propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
	}

	protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
		propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
	}

	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		Project project = (Project) evt.getSource();

		if (evt.getPropertyName().equals("project")) {
			// the ganttMap holds all ganttEvents (ID, event) and helps when adding dependencies
			TreeMap<Integer, GanttEvent> ganttMap = new TreeMap<Integer, GanttEvent>();
			this.getGanttComposite().clearChart();
			// only put top-level tasks (i.e. not subtasks) in the Gantt chart
			for (Task task : project.getTopLevelTasklist()) {
				// define the ganttEvent: start date, end date, title)
				Calendar startDate = Calendar.getInstance();
				Calendar endDate = Calendar.getInstance();
				endDate.setTime(task.getDeadline());
				startDate.setTime(endDate.getTime());
				startDate.add(Calendar.DAY_OF_MONTH, (-1) * task.getDuration() + 1);
				// add the ganttEvent to the chart
				GanttEvent ganttEvent = new GanttEvent(this, task.getTitle(), startDate, endDate, 0);
				// make sure the event cannot be edited
				ganttEvent.setResizable(false);
				ganttEvent.setMoveable(false);
				ganttEvent.setTextDisplayFormat("#name#");
				// populate the ganttMap
				ganttMap.put(task.getId(), ganttEvent);
			}
			// iterate over all dependencies and add a connection to the Gantt chart
			for (Map.Entry<Integer, Integer> dependency : project.getDependencyMap().entrySet()) {
				// get the Task IDs for the dependent tasks
				int first = dependency.getKey();
				int second = dependency.getValue();
				// get the corresponding events
				GanttEvent ganttEventFirst = ganttMap.get(first);
				GanttEvent ganttEventSecond = ganttMap.get(second);
				this.addConnection(ganttEventFirst, ganttEventSecond);
			}
		}
	}

}
